package fr.cephb.joperon.core.db;

import java.io.File;


import com.sleepycat.db.Cursor;
import com.sleepycat.db.DatabaseEntry;
import com.sleepycat.db.DatabaseException;
import com.sleepycat.db.DatabaseType;
import com.sleepycat.db.LockMode;
import com.sleepycat.db.OperationStatus;

import fr.cephb.berkeley.DBUtils;
import fr.cephb.joperon.core.Operon;
import fr.cephb.joperon.core.bio.Assembly;
import fr.cephb.joperon.core.bio.DNASEQArray;
import fr.cephb.joperon.core.entities.DnaSeq;
import fr.cephb.util.CloseableIterator;
import fr.cephb.util.Pair;

public class DNASeqDB
	extends AbstractSequenceDB<DNASEQArray>
	{
	private Assembly assembly;
	public DNASeqDB(Operon operon,Assembly assembly)
		{
		super(operon);
		}
	
	/** @return the assembly */
	public Assembly getAssembly() {
		return assembly;
		}
	
	@Override
	public DatabaseType getDatabaseType() {
		throw new UnsupportedOperationException("TODO");
		}
	
	@Override
	public String getName()
		{
		return getAssemblySpecificName(getAssembly(),"seqmap");
		}
	
	
 
	@Override
	protected DatabaseEntry valueToEntry(DNASEQArray value)
			throws DatabaseException
		{
		//TODO
		throw new UnsupportedOperationException("TODO");
		}
	
	
	@Override
	protected int convertByteLengthToSeqLength(int bytes) {
		return bytes/DnaSeq.SIZEOF;
		}
	
	
	
	@Override
	public DNASEQArray readValue(DatabaseEntry key,DatabaseEntry data) throws DatabaseException
		{
		return new DNASEQArray
			(
			readKey(key,data),
			data.getData(),
			0,
			data.getSize()
			);
		}

	/** get  a sequence
	 * @param acn the sequence id
	 * @return the sequence of null if it was not found
	 * */
	public DNASEQArray getSequenceByAcn(String acn) throws DatabaseException
		{
		DatabaseEntry key = new DatabaseEntry(DBUtils.string2CString(acn));
		DatabaseEntry data = get(key);
		return data==null?null:readValue(key,data);
		}
	
	/** get a fragment of a sequence
	 * @param acn the sequence id
	 * @param start the sequence start offset
	 * @param end the sequence end offset (excluded)
	 * @return the sub-sequence of null if it was not found
	 * */
	public DNASEQArray getSubSequence(String acn,int start,int length) throws DatabaseException
		{
		DatabaseEntry key = new DatabaseEntry(DBUtils.string2CString(acn));
		Cursor c=null;
		try {
			c=cursor();
			DatabaseEntry data= new DatabaseEntry();

			data.setPartial(
					start*DnaSeq.SIZEOF,
					(length)*DnaSeq.SIZEOF,
					true);
			if(c.getSearchKey(key, data, LockMode.DEFAULT)==OperationStatus.SUCCESS)
				{
				return data==null?null:readValue(key,data);
				}
			return null;
			}
		finally
			{
			DBUtils.safeClose(c);
			}
		}
	
	
	public static void main(String[] args)
	{
	try {
		Operon operon= Operon.newInstance(new File(Operon.DB_HOME_CEPH));
		DNASeqDB db= new DNASeqDB(operon,Assembly.HSA_NCBI_BUILD_36);
		db.open();
		
		System.err.println("Sequence size:"+db.getSequenceSize("NC_001807.4"));
		
		int i=0;
		CloseableIterator<Pair<String,DNASEQArray>> iter=db.listKeyValues();
		while(iter.hasNext())
			{
			if(i++>1) break;
			Pair<String,DNASEQArray> g=iter.next();
			System.err.println(g.first());
			g.second().toFasta(System.out,0,300);
			
			DNASEQArray test= db.getSequenceByAcn(g.first());
			test.toFasta(System.out,0,300);
			test= db.getSubSequence(g.first(),0,300);
			test.toFasta(System.out);
			}
		iter.close();
		db.close();
		System.err.println(i);
	} catch (Exception e) {
		e.printStackTrace();
	}
	}
	
}
